#ifndef __PROCESS_POOL_HPP__
#define __PROCESS_POOL_HPP__

#include <iostream>
#include <string>
#include <stdlib.h>
#include <cstdio>
#include <vector>
#include <functional>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Test.hpp"

// 创建管道的数量
const int gdefault_channel_num = 5;
// 创建一个回调函数
using callback_t = std::function<void(int fd)>;

class Channel
{ // 创建信道
public:
    Channel() {}
    Channel(int fd, std::string &name, pid_t num) : _wfd(fd), _channel_name(name), _sub_target(num)
    {
        srand(time(nullptr) ^ getpid() ^ 0x777);
    }
    ~Channel() {}

    // 打印测试
    void DeBugPrint()
    {
        printf("channel name : %s wfd : %d target : %d\n", _channel_name.c_str(), _wfd, _sub_target);
    }
    // 获取channel属性
    int Getwfd() { return _wfd; }
    std::string Getname() { return _channel_name; }
    pid_t GetTarget() { return _sub_target; }
    // 关闭操作
    void Close() { close(_wfd); }
    // 等待操作
    void Wait()
    {
        pid_t rid = waitpid(_sub_target, nullptr, 0);
        (void)rid;
    }

private:
    int _wfd;
    std::string _channel_name;
    pid_t _sub_target;
};

class Processpool
{
public:
    Processpool(int num = gdefault_channel_num) : _processnum(num)
    {
    }
    ~Processpool()
    {
    }
    bool InitProcessPool(callback_t cb)
    {
        for (int i = 0; i < _processnum; i++)
        {
            // 创建管道
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                return false;

            // 创建进程
            pid_t id = fork();
            if (id < 0)
            {
                perror("fork");
                return false;
            }
            else if (id == 0)
            {
                std::cout << getpid() << " 关闭：" ;
                for(auto &c : _channels)
                {
                    c.Close();
                    std::cout << c.Getwfd() << " ";
                }
                std::cout << "\n";
                // 子进程,关闭读写端，父进程写入，子进程读取
                close(pipefd[1]);

                cb(pipefd[0]);

                exit(0);
            }
            // 父进程
            close(pipefd[0]);
            std::string name = "channel-" + std::to_string(i);
            // 将信道逐个放入容器中
            _channels.emplace_back(pipefd[1], name, id);
        }
        return true;
    }
    // 父进程操作子进程完成相应的工作
    // 父进程轮询选择子进程操作
    void CtrlProcessCore(int &index)
    {
        // 选择管道
        int who = index;
        index++;
        index %= _channels.size();
        // 选择任务
        int x = rand() % task.size();
        // 派送任务
        std::cout << _channels[who].Getname() << "子进程正在工作中" << std::endl;
        write(_channels[who].Getwfd(), &x, sizeof(x));
        sleep(2);
    }
    void PolingCtrlAllProcess()
    {
        int index = 0;
        while (true)
        {
            CtrlProcessCore(index);
        }
    }
    //选择次数操作
    void PolingCtrlProcess(int num)
    {
        int index = 0;
        int count = num;
        while (count--)
        {
            CtrlProcessCore(index);
        }
    }
    // 父进程等待子进程退出
    void ProcessWaint()
    {
        for(auto &c : _channels)
        {
            c.Close();
            c.Wait();
        }
        // // 关闭进程
        // for (auto &c : _channels)
        // {
        //     c.Close();
        // }
        // // 回收僵尸进程
        // for (auto &c : _channels)
        // {
        //     c.Wait();
        //     std::cout << "回收子进程: " << c.GetTarget() << std::endl;
        // }
    }

private:
    std::vector<Channel> _channels;
    int _processnum;
};

#endif
